﻿using System;
using Autodesk.Revit.DB;
using YJKArch.Utils;

namespace YJKArch.Aproll.DataDefine
{
	public class BaseLineSegment
	{
		public EdgeInfo Segment
		{
			get
			{
				return this.m_EdgeInfo;
			}
			set
			{
				this.m_EdgeInfo = value;
			}
		}

		public XYZ Center
		{
			get
			{
				return this.Segment.Center;
			}
		}

		public double Radius
		{
			get
			{
				return this.Segment.Radius;
			}
		}

		public BaseLineSegment()
		{
		}

		public BaseLineSegment(BaseLineSegment other)
		{
			this.m_EdgeInfo = other.m_EdgeInfo;
		}

		public BaseLineSegment(EdgeInfo edgeInfo)
		{
			this.m_EdgeInfo = edgeInfo;
		}

		public bool IsEqual(BaseLineSegment other)
		{
			return this.IsEqual(other.Segment);
		}

		public bool IsEqual(EdgeInfo edgeInfo)
		{
			double eps = 0.001;
			return (Geometry.IsEqual(this.Segment.StartPoint, edgeInfo.StartPoint, eps) && Geometry.IsEqual(this.Segment.EndPoint, edgeInfo.EndPoint, eps) && Geometry.IsEqual(this.Segment.Bulge, edgeInfo.Bulge, eps)) || (Geometry.IsEqual(this.Segment.StartPoint, edgeInfo.EndPoint, eps) && Geometry.IsEqual(this.Segment.EndPoint, edgeInfo.StartPoint, eps) && Geometry.IsEqual(this.Segment.Bulge, -edgeInfo.Bulge, eps));
		}

		private BaseLineSegment._tagPositionType TestPointPositionType(XYZ ptCurNodePos)
		{
			double val = this.Segment.StartPoint.DistanceTo(ptCurNodePos);
			double val2 = this.Segment.EndPoint.DistanceTo(ptCurNodePos);
			if (Geometry.LessThan(val, val2))
			{
				return BaseLineSegment._tagPositionType._StartNode;
			}
			if (Geometry.GreaterThan(val, val2))
			{
				return BaseLineSegment._tagPositionType._EndNode;
			}
			return BaseLineSegment._tagPositionType._OtherPoint;
		}

		public bool GetAngle(XYZ ptCurNodePos, ref double curAngle)
		{
			BaseLineSegment._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == BaseLineSegment._tagPositionType._StartNode)
			{
				if (!this.Segment.IsArc)
				{
					curAngle = Geometry.getAngle(this.Segment.StartPoint, this.Segment.EndPoint);
				}
				else if (Geometry.LessThan(this.Segment.Bulge, 0.0))
				{
					XYZ ptCenter = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.Segment.StartPoint, this.Segment.EndPoint, this.Segment.Bulge, ref ptCenter);
					curAngle = Geometry.getAngle(ptCenter, this.Segment.StartPoint);
					curAngle = Geometry.formatAngle(curAngle - Math.PI*.5);
				}
				else
				{
					XYZ ptCenter2 = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.Segment.StartPoint, this.Segment.EndPoint, this.Segment.Bulge, ref ptCenter2);
					curAngle = Geometry.getAngle(ptCenter2, this.Segment.StartPoint);
					curAngle = Geometry.formatAngle(curAngle + Math.PI*.5);
				}
				return true;
			}
			if (tagPositionType == BaseLineSegment._tagPositionType._EndNode)
			{
				if (!this.Segment.IsArc)
				{
					curAngle = Geometry.getAngle(this.Segment.EndPoint, this.Segment.StartPoint);
				}
				else if (Geometry.LessThan(this.Segment.Bulge, 0.0))
				{
					XYZ ptCenter3 = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.Segment.StartPoint, this.Segment.EndPoint, this.Segment.Bulge, ref ptCenter3);
					curAngle = Geometry.getAngle(ptCenter3, this.Segment.EndPoint);
					curAngle = Geometry.formatAngle(curAngle + Math.PI*.5);
				}
				else
				{
					XYZ ptCenter4 = new XYZ(0.0, 0.0, 0.0);
					Geometry.GetCenterWithBulge(this.Segment.StartPoint, this.Segment.EndPoint, this.Segment.Bulge, ref ptCenter4);
					curAngle = Geometry.getAngle(ptCenter4, this.Segment.EndPoint);
					curAngle = Geometry.formatAngle(curAngle - Math.PI*.5);
				}
				return true;
			}
			return false;
		}

		public bool GetWinding(XYZ ptCurNodePos, ref int winding)
		{
			BaseLineSegment._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == BaseLineSegment._tagPositionType._StartNode)
			{
				winding = 1;
				if (!this.Segment.IsArc)
				{
					winding = 0;
				}
				if (Geometry.LessThan(this.Segment.Bulge, 0.0))
				{
					winding = -1;
				}
				return true;
			}
			if (tagPositionType == BaseLineSegment._tagPositionType._EndNode)
			{
				winding = -1;
				if (!this.Segment.IsArc)
				{
					winding = 0;
				}
				if (Geometry.LessThan(this.Segment.Bulge, 0.0))
				{
					winding = 1;
				}
				return true;
			}
			return false;
		}

		public EdgeInfo CurSegment(XYZ ptCurNodePos)
		{
			BaseLineSegment._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == BaseLineSegment._tagPositionType._StartNode)
			{
				return new EdgeInfo(this.Segment);
			}
			if (tagPositionType == BaseLineSegment._tagPositionType._EndNode)
			{
				return new EdgeInfo(this.Segment.ReverseTo());
			}
			return null;
		}

		public XYZ CurStartPoint(XYZ ptCurNodePos)
		{
			BaseLineSegment._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == BaseLineSegment._tagPositionType._StartNode)
			{
				return this.Segment.StartPoint;
			}
			if (tagPositionType == BaseLineSegment._tagPositionType._EndNode)
			{
				return this.Segment.EndPoint;
			}
			return null;
		}

		public XYZ CurEndPoint(XYZ ptCurNodePos)
		{
			BaseLineSegment._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == BaseLineSegment._tagPositionType._StartNode)
			{
				return this.Segment.EndPoint;
			}
			if (tagPositionType == BaseLineSegment._tagPositionType._EndNode)
			{
				return this.Segment.StartPoint;
			}
			return null;
		}

		public double CurBulge(XYZ ptCurNodePos)
		{
			double result = 0.0;
			if (!this.Segment.IsArc)
			{
				return result;
			}
			BaseLineSegment._tagPositionType tagPositionType = this.TestPointPositionType(ptCurNodePos);
			if (tagPositionType == BaseLineSegment._tagPositionType._StartNode)
			{
				result = this.Segment.Bulge;
			}
			else if (tagPositionType == BaseLineSegment._tagPositionType._EndNode)
			{
				result = -this.Segment.Bulge;
			}
			return result;
		}

		public bool IsOverlap(BaseLineSegment other)
		{
			if (this.Segment.IsArc && other.Segment.IsArc)
			{
				XYZ xyz = null;
				XYZ xyz2 = null;
				XYZ ptS = this.Segment.StartPoint;
				XYZ ptE = this.Segment.EndPoint;
				if (Geometry.IsEqual(this.Segment.Normal, -XYZ.BasisZ))
				{
					ptS = this.Segment.EndPoint;
					ptE = this.Segment.StartPoint;
				}
				XYZ ptS2 = other.Segment.StartPoint;
				XYZ ptE2 = other.Segment.EndPoint;
				if (Geometry.IsEqual(other.Segment.Normal, -XYZ.BasisZ))
				{
					ptS2 = other.Segment.EndPoint;
					ptE2 = other.Segment.StartPoint;
				}
				Geometry.OverlapType overlapType = Geometry.IsOverlapOfTwoArc(ptS, ptE, this.Segment.Center, ptS2, ptE2, other.Segment.Center, ref xyz, ref xyz2, 1E-09);
				if (overlapType != Geometry.OverlapType._OT_Linked && overlapType != Geometry.OverlapType._OT_None)
				{
					return true;
				}
			}
			else if (!this.Segment.IsArc && !other.Segment.IsArc)
			{
				XYZ xyz3 = null;
				XYZ xyz4 = null;
				Geometry.OverlapType overlapType2 = Geometry.IsOverlapOfTwoLine(this.Segment.StartPoint, this.Segment.EndPoint, other.Segment.StartPoint, other.Segment.EndPoint, ref xyz3, ref xyz4, true, 1E-09);
				if (overlapType2 != Geometry.OverlapType._OT_Linked && overlapType2 != Geometry.OverlapType._OT_None)
				{
					return true;
				}
			}
			return false;
		}

		private EdgeInfo m_EdgeInfo;

		private enum _tagPositionType
		{
			_StartNode,
			_EndNode,
			_OtherPoint
		}
	}
}
